package jmine.tec.script.persistent.dao;

import java.util.List;

import jmine.tec.annotations.Unmodifiable;
import jmine.tec.script.persistent.domain.Script;
import jmine.tec.script.persistent.si.ScriptSystemIdentifier;

import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import bancosys.tec.persist.dao.SystemEntityDAO;

/**
 * DAO da entidade {@link Script}.
 * 
 * @author Rafael Volpato
 * @date May 28, 2010
 */
@Unmodifiable
public class ScriptDAO extends SystemEntityDAO<Script, ScriptSystemIdentifier> {

    private static final Integer BASE_SCRIPT_DISCRIMINATOR = 0;

    /**
     * {@inheritDoc}
     * 
     * @deprecated never use find by example
     */
    @Override
    @Deprecated
    public List<Script> findByExample(Script example, boolean literal, String... excludeProperties) {
        Criteria criteria = this.createCriteria();
        criteria = criteria.add(this.mountExample(example, literal, excludeProperties));

        if (example.getPurpose() != null) {
            Criteria criteriaPurpose = criteria.createCriteria("purpose");
            if (example.getPurpose().getId() != null) {
                criteriaPurpose = criteriaPurpose.add(Restrictions.eq("id", example.getPurpose().getId()));
            } else {
                criteriaPurpose = criteriaPurpose.add(this.mountExample(example.getPurpose(), literal));
            }
        }

        return this.executeQuery(criteria);
    }

    /**
     * Encontra a lista de scripts com o proposito passado.
     * 
     * @param mnemonicoPurpose mnemonico do proposito.
     * @return lista de scripts com o proposito passado.
     */
    public List<Script> findByPurpose(String mnemonicoPurpose) {
        Criteria crit = this.createCriteria();
        crit.createCriteria("purpose").add(Restrictions.eq("mnemonico", mnemonicoPurpose));
        return this.executeQuery(crit);
    }

    /**
     * Busca scripts para pacote de exportação, deve retornar apenas scripts "base", não subclasses.
     * 
     * @param language language
     * @return lista de scripts
     */
    public List<Script> findPackScripts(ScriptLanguageIdentifier language) {
        Criteria criteria = this.createCriteria();
        criteria.add(Restrictions.eq("discriminator", BASE_SCRIPT_DISCRIMINATOR));
        if (language != null) {
            criteria.add(Restrictions.eq("language.id", language.getSystemId()));
        }
        criteria.addOrder(Order.asc("id"));
        return this.executeQuery(criteria);
    }

    /**
     * Finds all scripts that use the given script as API
     * 
     * @param api api
     * @return List of Scripts
     */
    public List<Script> findByAPI(Script api) {
        Criteria criteria = this.createCriteria();
        criteria.createCriteria("apis").add(Restrictions.idEq(api.getId()));
        return this.executeQuery(criteria);
    }

    /**
     * Finds all scripts that have
     * 
     * @param init init
     * @return List of Scripts
     */
    public List<Script> findByInitScript(Script init) {
        Criteria criteria = this.createCriteria();
        criteria.createCriteria("purpose").createCriteria("initScripts").add(Restrictions.idEq(init.getId()));
        criteria.add(Restrictions.eq("language", init.getLanguage()));
        return this.executeQuery(criteria);
    }

}
